#include "EventLoop.hpp"
#include "TcpServer.hpp"
#include "Threadpool.hpp"
#include <iostream>


using std::cout;
using std::endl;


class Mytask
{
public:
    Mytask(const string & msg, wd::TcpConnectionPtr conn)
    : _msg(msg)
    , _conn(conn)
    {}

    //process函数的调用是在线程池中的某一个子线程
    void process()
    {
        printf("Mytask::process is running.\n");
        //进行业务逻辑的处理
        //decode
        //compute
        //encode
        //
        string response = _msg;
        //
        //发送数据, 这是在子线程(计算线程)中完成的
        //按照职责分离的原则，计算线程不应该进行数据的发送,
        //因为数据的发送要交给IO线程来完成
        //在这里应该要通知IO线程完成数据的发送
        //_conn->send(response);
        _conn->sendInLoop(response);
    }

private:
    string _msg;
    wd::TcpConnectionPtr _conn;
};


class EchoServer
{
public:
    EchoServer(int threadNum,
               int queSize,
               unsigned short port, 
               const string & ip = "0.0.0.0")
    : _threadpool(threadNum, queSize)
    , _server(port, ip)
    {
        using namespace std::placeholders;
        _server.setAllCallbacks(std::bind(&EchoServer::onConnection, this, _1),
                                std::bind(&EchoServer::onMessage, this, _1),
                                std::bind(&EchoServer::onClose, this, _1));
    }

    void start()
    {
        _threadpool.start();
        _server.start();
    }

    void onConnection(wd::TcpConnectionPtr conn)
    {
        //连接建立时的处理
        cout << conn->toString() << " has connected." << endl;

    }

    void onMessage(wd::TcpConnectionPtr conn)
    {
        string msg = conn->receive();
        cout << "receive:" << msg << endl;

        //当接收到消息之后，数据的处理应该交给线程池来完成
        Mytask task(msg, conn);
        _threadpool.addTask(std::bind(&Mytask::process, task));
    }

    void onClose(wd::TcpConnectionPtr conn)
    {
        //连接断开时的处理
        cout << conn->toString() << " has closed." << endl;
    }
private:
    wd::Threadpool _threadpool;
    wd::TcpServer _server;
};

int main()
{
    EchoServer server(4, 10, 8000);
    server.start();

    return 0;
}

